package com.encyclopedia.config;

import com.encyclopedia.handler.ExceptionHandler;
import com.encyclopedia.handler.TokenFilter;
import com.encyclopedia.properties.ExcludeUrlProperties;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * @author MaLiang
 * @version 1.0
 * @date 2024-04-26 19:44
 */
@EnableWebSecurity
@Slf4j
@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Resource
    private TokenFilter tokenFilter;

    /**
     * 非法授权异常处理
     */
    @Resource
    private ExceptionHandler.AuthenticationPrint authenticationPrint;

    /**
     * 非法访问异常处理
     */
    @Resource
    private ExceptionHandler.AccessDeniedPrint accessDeniedPrint;

    /**
     * 权限路由处理器
     */
    @Autowired
    private ExcludeUrlProperties excludeUrlProperties;


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 禁用basic明文验证
                .httpBasic(AbstractHttpConfigurer::disable)
                // 前后端分离架构不需要csrf保护
                .csrf(AbstractHttpConfigurer::disable)
                // 禁用默认登录页
                .formLogin(AbstractHttpConfigurer::disable)
                // 禁用默认登出页
                .logout(AbstractHttpConfigurer::disable)
                // 异常处理
                .exceptionHandling(exceptions ->
                        //非法授权自定义响应
                        exceptions.authenticationEntryPoint(authenticationPrint)
                                //非法访问自定义响应
                                .accessDeniedHandler(accessDeniedPrint))
                //路径处理
                .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
                        // 匿名路径
                        .requestMatchers(excludeUrlProperties.getExcludeUrl()).anonymous()
                        // 静态资源
                        .requestMatchers(excludeUrlProperties.getStaticUrl()).permitAll()
                        // 允许任意请求被已登录用户访问，不检查Authority
                        .anyRequest().authenticated())
                // 自定义Token过滤器
                .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
        log.info("Security核心已配置完成!");
        return httpSecurity.build();
    }

    /**
     * Security异步配置
     *
     * @return 初始化bean
     */
    @Bean
    public InitializingBean initializingBean() {
        return () -> SecurityContextHolder
                .setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
    }
}
